import numpy as np
import math
import Env.Tools.MathFunc
import math

import numpy as np

import Env.Tools.MathFunc


class utility:
    def __init__(self,n_friend,n_enemy,Location_F,Location_E):
        self.NN=np.zeros([3,4])   # NN修正后权值 3*4的零矩阵
        self.RW=np.zeros([n_friend,n_enemy])   # RW第i架飞机传感器证据 4*4的零矩阵
        self.MW=np.zeros([n_friend,n_enemy])   # MW第i架飞机武器证据 4*4的零矩阵
        self.WO=np.zeros([n_friend,n_enemy,4])   # WO合成后的有效性 4*4*4的三维零矩阵
        # 合成用权值
        self.Quan_m=np.zeros([3,4])
        self.Quan_r=np.zeros([3,4])
        self.Quan_s=np.zeros([2,4])

        self.KK=0.

        assert Location_E.shape==(n_enemy,3),'输入敌方坐标格式有误'+str(Location_E.shape)  #判断坐标格式是否为三维
        assert Location_F.shape==(n_friend,3),'输入我方坐标格式有误'+str(Location_F.shape)
        self.Location_E = Location_E    # 敌方坐标
        self.Location_F = Location_F  # 我方坐标

        self.n_friend=n_friend
        self.n_enemy=n_enemy

        self.Computer_Initial()

    def Computer_Initial(self):
        self.GetQuanData()

    def GetQuanData(self):
        # 设置传感器修正权值 Quan_r
        r_file=open('Env/data/传感器权值.txt')
        m_file=open('Env/data/武器权值.txt')
        s_file=open('Env/data/单机权值.txt')

        for i in range(3):
            r_data=r_file.readline().split()
            m_data=m_file.readline().split()
            for j in range(1,4):
                self.Quan_r[i][j]=r_data[j-1]
                self.Quan_m[i][j] = m_data[j - 1]
        # print(self.Quan_r)
        # print(self.Quan_m)

        for i in range(2):
            s_data=s_file.readline().split()
            for j in range(1,4):
                self.Quan_s[i][j]=s_data[j-1]
        # print(self.Quan_s)

        r_file.close()
        m_file.close()
        s_file.close()

    # 计算初始化
    def Run(self):
        # 我方飞机{0}对地方目标{1}攻击有效性计算
        for i in range(self.n_friend):
            for j in range(self.n_enemy):
                # print('我方飞机{0}对地方目标{1}攻击有效性计算'.format(str(i+1),str(j+1)))
                self.Computer_W_D(i,j)
                self.Set_RA()
                self.Set_K()
                self.Set_RU(i)
                self.Set_MA()
                self.Set_K()
                self.Set_MU(i)
                self.Set_SA(i)
                self.Single(i,j)
                # print("我方飞机传感器证据：")
                # print(self.RW)
                # print("我方飞机武器证据：")
                # print(self.MW)

        return self.噪音(self.WO)

    # 计算敌方第i架飞机对我方第j架飞机的6个参数
    def Computer_W_D(self, i, j):
        Calangdis = Env.Tools.MathFunc.Cal_Ang_dis()
        水平距离 = Calangdis.计算水平距离(self.Location_F[i][0], self.Location_F[i][1],
                                self.Location_E[j][0], self.Location_E[j][1])
        方位夹角_0 = Calangdis.计算方位夹角_cos(self.Location_F[i][0], self.Location_F[i][1],
                                self.Location_E[j][0], self.Location_E[j][1])

        """似乎没啥用
            方位夹角_PI = Calangdis.计算方位夹角_tan(self.Location_F[i][0],self.Location_F[i][1],
                                             self.Location_E[j][0],self.Location_E[j][1])

        """
        俯仰角_PI = Calangdis.计算俯仰角(self.Location_F[i][0], self.Location_F[i][1],
                                self.Location_F[i][2], self.Location_E[j][0],
                                self.Location_E[j][1], self.Location_E[j][2])
        Proof = Env.Tools.MathFunc.CalProof()
        Proof.GetHDPara_R(0, 水平距离)
        Proof.GetAAPara_R(1, 方位夹角_0)
        Proof.GetPAPara_R(2, 俯仰角_PI)
        Proof.GetHDPara_M(3, 水平距离)
        Proof.GetAAPara_M(4, 方位夹角_0)
        Proof.GetPAPara_M(5, 俯仰角_PI)

        self.RR = Proof.RR
        self.MM = Proof.MM
        # print('RR矩阵\r\n{0}'.format(self.RR))
        # print('MM矩阵\r\n{}'.format(self.MM))

    # 传感器证据基本可信数修正函数(我方 VS 敌方)
    def Set_RA(self):
        SigmaN = np.zeros(3)  # 用来求和
        # 修正基本可信数
        for i in range(3):
            for j in range(3):
                self.NN[i][j] = self.Quan_r[i][j] * self.RR[i][j]
                SigmaN[i] += self.NN[i][j]
            self.NN[i][3] = 1 - SigmaN[i]

    # 传感器证据/武器证据合成时，K值的计算(我方 VS 敌方)
    def Set_K(self):
        SigmaK = 0.  # 用来求和

        for a in range(1, 4):
            for b in range(1, 4):
                for c in range(1, 4):
                    if ((a & b & c) == 0):
                        SigmaK = SigmaK + self.NN[0][a] * self.NN[1][b] * self.NN[2][c]

        self.KK = 1 / (1 - SigmaK)

    # 我方第i架飞机传感器证据的合成
    def Set_RU(self, i):
        for j in range(1, 3):
            SigmaU = 0.
            for a in range(1, 4):
                for b in range(1, 4):
                    for c in range(1, 4):
                        if ((a & b & c) == j):
                            SigmaU = SigmaU + self.NN[0][a] * self.NN[1][b] * self.NN[2][c]  # 什么含义？
            self.RW[i][j] = self.KK * SigmaU
        self.RW[i][3] = 1 - self.RW[i][1] - self.RW[i][2]

    # 武器证据基本可信数修正函数(我方 VS 敌方)
    def Set_MA(self):
        SigmaN = np.zeros(3)  # 用来求和
        # 修正基本可信数
        for i in range(3):
            for j in range(3):
                self.NN[i][j] = self.Quan_m[i][j] * self.MM[i][j]
                SigmaN[i] += self.NN[i][j]
            self.NN[i][3] = 1 - SigmaN[i]

    # 我方第i架飞机武器证据的合成
    def Set_MU(self,i):
        for j in range(1,3):
            SigmaU = 0.
            for a in range(1,4):
                for b in range(1,4):
                    for c in range(1,4):
                        if ((a & b & c) == j):
                            SigmaU = SigmaU + self.NN[0][a] * self.NN[1][b] * self.NN[2][c]
            self.MW[i][j]=self.KK * SigmaU
        self.MW[i][3] = 1 - self.MW[i][1] - self.MW[i][2]

    # 单机基本可信数修正函数(flag为true,代表我方)
    def Set_SA(self,i,flag=True):
        if flag:
            self.RW[i][1] = self.Quan_s[0][1] * self.RW[i][1]
            self.RW[i][2] = self.Quan_s[0][2] * self.RW[i][2]
            self.RW[i][3] = 1 - self.RW[i][1] - self.RW[i][2]
            self.MW[i][1] = self.Quan_s[1][1] * self.MW[i][1]
            self.MW[i][2] = self.Quan_s[1][2] * self.MW[i][2]
            self.MW[i][3] = 1 - self.MW[i][1] - self.MW[i][2]

        #else:
            #self.RD[i][1] = self.Quan_s[0][1] * self.RD[i][1]
            #self.RD[i][2] = self.Quan_s[0][2] * self.RD[i][2]
            #self.RD[i][3] = 1 - self.RD[i][1] - self.RD[i][2]
            #self.MD[i][1] = self.Quan_s[1][1] * self.MD[i][1]
            #self.MD[i][2] = self.Quan_s[1][2] * self.MD[i][2]
            #self.MD[i][3] = 1 - self.MD[i][1] - self.MD[i][2]

    # 我方第i架飞机对敌方第j个目标的攻击有效性的合成
    def Single(self,i,j):

        SK=1/(1-self.RW[i][1]* self.MW[i][2] - self.RW[i][2] * self.MW[i][1])
        self.WO[i][j][1] = SK * (self.RW[i][1] * self.MW[i][1] + self.RW[i][1] * self.MW[i][3] +
                                 self.RW[i][3] * self.MW[i][1])
        self.WO[i][j][2] = SK * (self.RW[i][2] * self.MW[i][2] + self.RW[i][2] * self.MW[i][3] +
                                 self.RW[i][3] * self.MW[i][2])
        self.WO[i][j][3] = SK * self.RW[i][3] * self.MW[i][3]

    def 噪音(self,matrix):    # TODO (zrc) 可信度进行0%到6%的处理，再进行tanh。可信度为命中，不可信为没命中，不确定为差点命中
        ran=np.random
        # 对WO矩阵中的[i][j][]中的最后一个元素进行运算和更新。
        for i in matrix:
            for j in i:
                j[1] *= math.tanh(1 - (ran.randint(0, 6) / 100))
                j[2]=1-j[0]-j[1]-j[3]
        return matrix

class Attack:
    ##初始化红蓝双方火力对抗的矩阵。接收参数为我方和敌方的火力分配，为一个数组。
    # 如friend:（1，0，0，3）表示我方第一架无人机攻击地方第一架无人机，第二，三架无人机不进攻，第四架无人机进攻敌方第三架，等
    #先根据A与B双方的火力分配生成相应的攻击矩阵，再相加.得到火力分配矩阵
    @staticmethod
    def judge_matrix(friend,enemy):         #未用到
        fire_matrixA = np.zeros((len(friend), len(enemy)))
        for i in range(4):
            if friend[i]!=0:
                fire_matrixA[i][friend[i]-1]=1

        fire_matrixB = np.zeros((len(friend), len(enemy)))
        for i in range(4):
            if enemy[i]!=0:
                fire_matrixB[enemy[i]-1][i]=2

        fire_matrix = fire_matrixA + fire_matrixB
        return fire_matrix

    # TODO (zrc) 计算命中矩阵和返回摧毁情况,输入为概率矩阵和火力分配矩阵;返回摧毁矩阵
    @staticmethod
    def att_result(p, matrix):   # 第一个参数是命中概率矩阵，第二个是导弹命中时间状态列表(即攻击状态矩阵)

        index=np.where(matrix > 0)   # 返回两个数组，第一个保存行坐标，第二个表示列坐标，用于选择攻击状态矩阵为零的元素
        # print(index,"吼吼吼吼吼吼吼吼吼吼吼吼吼吼吼吼吼吼吼吼")    为什么输出不出来
        result = np.zeros([len(matrix),len(matrix[0])])
        for i,j in zip(index[0],index[1]):
            possible = p[i][j]
            print(possible)
            result[i][j] = Attack.lunpan(possible[1],possible[3])

        return result       # 返回我方i对敌方j损毁情况，返回的可能是多个结果。并且返回的矩阵维数不确定！！！！！！！！！！！！！


    @staticmethod
    def lunpan(p1,p2):  # p1命中概率，p2不确定概率
        ran=np.random.rand()
        if ran>=0 and ran<=p1:
            return 2        # 命中
        elif ran<=p2+p1:
            return 1        # 差点命中 ，即不确定
        elif ran<=1:
            return 0        # 没有命中





